[CELEBORN-2378] Fix CongestionController never resuming due to Netty pool overhead in getTotalPendingBytes()#3756
[CELEBORN-2378] Fix CongestionController never resuming due to Netty pool overhead in getTotalPendingBytes()#3756Deegue wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Updates worker congestion-control pending-bytes calculation to avoid Netty pooled allocator overhead so the worker can correctly resume once actual pending data drops below the low watermark.
Changes:
- Switch
CongestionController.getTotalPendingBytes()fromMemoryManager.getMemoryUsage()toMemoryManager.getPinnedMemory().
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public long getTotalPendingBytes() { | ||
| return MemoryManager.instance().getMemoryUsage(); | ||
| return MemoryManager.instance().getPinnedMemory(); | ||
| } |
| public long getTotalPendingBytes() { | ||
| return MemoryManager.instance().getMemoryUsage(); | ||
| return MemoryManager.instance().getPinnedMemory(); | ||
| } |
|
It's ok for me, but if we change |
zaynt4606
left a comment
There was a problem hiding this comment.
In non-POOLED mode (UNPOOLED or ADAPTIVE), pooledByteBufAllocators stays empty because both fill sites guard with if (allocatorType == POOLED).
So getNettyPinnedDirectMemory() sums an empty list and returns 0, making getTotalPendingBytes() underestimate pending data.
Suggested fix:
fall back to PlatformDependent.usedDirectMemory() when no pooled allocators exist, so non-POOLED configs retain the old behavior.
|
Thanks @zaynt4606 , added a fallback when no pooled allocators exist, we fall back to |
|
I also changed the code to keep the enter condition using Gentle ping @leixm @zaynt4606 for further ideas. |
| public long getActivePendingBytes() { | ||
| MemoryManager memoryManager = MemoryManager.instance(); | ||
| long pinnedMemory = memoryManager.getPinnedMemory(); | ||
| if (pinnedMemory == 0 && NettyUtils.getAllPooledByteBufAllocators().isEmpty()) { | ||
| return memoryManager.getMemoryUsage(); | ||
| } | ||
| return pinnedMemory; | ||
| } |
|
|
||
| protected void checkCongestion() { | ||
| try { | ||
| long pendingConsume = getTotalPendingBytes(); |
| logger.info( | ||
| "Pending consume and produce speed is lower than low watermark, exit congestion control"); | ||
| } |
… getTotalPendingBytes()
|
Offline discussed with @leixm , added cache and update interval for |
|
@Deegue, please discuss this in comments, instead of offline discussion. Otherwise, reviewers and others could not know the input of this change. BTW, please update the title and description according to updates. |
Thanks @SteNicholas, PR description updated. Previously we discussed if it's necessary to add a rate limit and interval to call |
| this.workerSource = workerSource; | ||
| this.sampleTimeWindowSeconds = sampleTimeWindowSeconds; | ||
| this.userInactiveTimeMills = conf.workerCongestionControlUserInactiveIntervalMs(); | ||
| this.activePendingBytesCacheIntervalMs = conf.workerPinnedMemoryCheckIntervalMs(); |
There was a problem hiding this comment.
The behavior of trimMemoryUsage() is controlled by current workerCongestionControlCheckIntervalMs (default 10ms) which this PR doesn't change.
Pinned memory check interval is designed to follow CelebornConf.WORKER_PINNED_MEMORY_CHECK_INTERVAL according to comments above.
| logger.info( | ||
| "Pending consume and produce speed is lower than low watermark, exit congestion control"); | ||
| } |
| if (overHighWatermark.get()) { | ||
| long activePendingBytes = getActivePendingBytes(); | ||
| if (activePendingBytes < workerTrafficQuota.diskBufferLowWatermark() | ||
| && workerProduceSpeed < workerTrafficQuota.workerProduceSpeedLowWatermark()) { | ||
| if (overHighWatermark.compareAndSet(true, false)) { |
What changes were proposed in this pull request?
Use
MemoryManager.instance().getPinnedMemory()for low watermark to exit congestion status when using pooled allocator.Why are the changes needed?
getMemoryUsage()returnsnettyUsedDirectMemory + sortMemory, which includes Netty's pooled allocator overhead.Change to
getPinnedMemory()which returnsnettyPinnedDirectMemory + sortMemoryinstead.As for unpooled allocator, we keep the same behavior as before.
Does this PR resolve a correctness bug?
Does this PR introduce any user-facing change?
No API change.
Workers with congestion control and pooled allocator will now correctly resume from congestion state when actual pending data drops below the low watermark.
How was this patch tested?
UTs